After reading through this tutorial, you may keep this tab
open and refer back to the tutorial as you complete the rest of the
survey.
Introduction
Technical
objective
Learn the basics of Bayesian parameter estimation, a Bayesian data
analysis technique, and how it differs from frequentist parameter
estimation
Substantive research
question
How do emotion regulation strategies moderate the association between
sleep and negative emotions?
Bayesian parameter
estimation
In this tutorial, we will be applying the Bayesian lens to the
estimation of parameters in a multilevel linear model. In
Bayesian parameter estimation, we view parameter
estimates as probability distributions, as opposed to point values.
Emotion
regulation
In the following Bayesian data analysis models, we will examine two
emotion regulation strategies, cognitive reappraisal
and expressive suppression, and whether they moderate
the association between hours of sleep at night and
negative affect the following day.
Briefly, in cognitive reappraisal, one changes the
way in which they think about an emotionally-inducing event in order to
alter their emotional response to that event. For example, instead of
thinking about an exam as a difficult and consequential test of their
abilities, a student might choose to frame the exam as an opportunity to
show what they have learned. In expressive suppression,
one regulates their emotions by inhibiting their external displays of
emotion. For example, a student who feels nervous about an upcoming exam
may stop themselves from showing a worried look on their face and
telling their friends that they feel nervous. More information on these
two emotion regulation strategies can be found in Gross & John
(2003).
The present study:
Emotion regulation, sleep, and negative affect
In our analysis, we will be looking at the relationships among these
emotion regulation strategies, sleep, and negative affect, also known as
negative emotion. An individual’s emotion regulation and coping
strategies are thought to moderate the impact of stress on sleep quality
(Kahn et al., 2013). We might also be interested in whether emotion
regulation strategies moderate the impact of sleep on negative emotions
the following day. In other words, does a particular emotion
regulation strategy help us better manage our negative emotions after a
night of poor sleep?
The data we are using come from the AMIB study, a multiple timescale
study of college students (Ram et al., 2012). In particular, we will be
looking at college students’ daily self-reports of their sleep and
negative affect over the course of eight days, as well as their
dispositional cognitive reappraisal and expressive suppression scores.
The data can be downloaded from https://thechangelab.stanford.edu/collaborations/the-amib-data/.
We will run a regression analysis using these data to get some
preliminary insights into the associations among emotion regulation,
sleep, and negative affect.
Preliminaries
Load libraries and
data
library(brms)
library(loo)
library(psych)
library(tidyverse)
We read in the data from the online repository.
# set filepath for data file
filepath <-
"https://raw.githubusercontent.com/The-Change-Lab/collaborations/main/AMIB/AMIB_persons.csv"
# read in the .csv file using the url() function
AMIB_persons <- read.csv(file=url(filepath),header=TRUE)
# set filepath for data file
filepath <-
"https://raw.githubusercontent.com/The-Change-Lab/collaborations/main/AMIB/AMIB_daily.csv"
# read in the .csv file using the url() function
AMIB_daily <- read.csv(file=url(filepath),header=TRUE)
Data
manipulation
We merge the daily-level variables (participant ID,
day, hours of sleep, and
negative affect) and the person-level variables
(participant ID, cognitive reappraisal
score, expressive suppression score) into a single
dataset.
# subset to day-level variables of interest
bpe_daily <- AMIB_daily[,c("id", "day", "slphrs", "negaff")]
# subset to person-level variables of interest
bpe_persons <- AMIB_persons[,c("id", "erq_reap", "erq_supp")]
# merge day- and person-level data
bpe_data <- merge(bpe_daily, bpe_persons, by = "id")
We center the emotion regulation questionnaire scores to facilitate
the interpretation of model results.
# center the erq subscale score variables for interpretability
bpe_data$erq_reap_c <- scale(bpe_data$erq_reap, center=TRUE,scale=FALSE)[,1]
bpe_data$erq_supp_c <- scale(bpe_data$erq_supp, center=TRUE,scale=FALSE)[,1]
Initial plots
Before running our models, it can be helpful to examine the raw
data.
Correlations and
distributions
# calculate correlations
# dropping the id and non-centered erq columns
cor(bpe_data[ ,c(-1, -5, -6)], use = "complete.obs")
## day slphrs negaff erq_reap_c erq_supp_c
## day 1.000000000 -0.0480824055 -0.141990043 0.007004748 -0.0210526130
## slphrs -0.048082405 1.0000000000 -0.155243242 0.001261147 -0.0004183473
## negaff -0.141990043 -0.1552432419 1.000000000 -0.002317911 0.0246226777
## erq_reap_c 0.007004748 0.0012611469 -0.002317911 1.000000000 -0.1337777409
## erq_supp_c -0.021052613 -0.0004183473 0.024622678 -0.133777741 1.0000000000
# plot correlations
pairs.panels(bpe_data[ ,c(-1, -5, -6)])

We see relatively weak correlations overall, but note a small
negative correlation between hours of sleep and
negative affect (-0.16), as well as a small negative
correlation between cognitive reappraisal and
expressive suppression (-0.13). We also observe a small
negative correlation between day in study and
negative affect (-0.14).
The distributions of the variables can be seen on the diagonal. Of
particular interest, we note that the distribution of cognitive
reappraisal scores has a negative skew, while the distribution
of expressive suppression scores is relatively
symmetrical.
Linear regression:
Negative affect vs. hours of sleep
We will now plot a simple, non-Bayesian linear regression of
negative affect vs. hours of sleep to
get a better sense of the association between our outcome variable and
our main predictor variable.
ggplot(data=bpe_data, aes(x=slphrs, y=negaff)) +
geom_jitter(width = 0.35) +
geom_smooth(method=lm, lty=1, size=2) +
xlab("Hours of Sleep") + ylab("Negative Affect Level") +
theme_classic() +
theme(axis.title=element_text(size=12),
axis.text=element_text(size=12),
plot.title=element_text(size=14, hjust=.5)) +
theme(text = element_text(family = "Times New Roman")) +
ggtitle("Negative Affect vs. Sleep")

In general, more hours of sleep is associated with
lower negative affect. However, many of the sleep
durations correspond to a wide range of negative affect
values, suggesting differences in negative affect
across individuals.
The Bayesian
approach
Bayes’ theorem
Before running our Bayesian models, we will briefly recap Bayes’
theorem. Bayes’ theorem gives us a mathematical expression for the
probability of a hypothesis, H, conditional on (that is, given existing
knowledge of) a body of evidence, E (Joyce, 2003/2021). The expression
for Bayes’ theorem is
\[ P(H|E)= \frac{P(E|H)P(H)}{P(E)}.
\] The posterior, \(P(H|E)\),
refers to the probability of the hypothesis being true after having
observed the evidence. The likelihood, \(P(E|H)\), refers to the probability of
observing the evidence in the case where the hypothesis is already true.
The prior, \(P(H)\), refers to the
probability of the hypothesis being true without having observed any
evidence. Finally, the normalizing constant, \(P(E)\), refers to the probability of the
evidence occurring independent of any hypothesis.
Bayesian
interpretation
In general, Bayes’ theorem operates under the assumption that our
refined degree of belief in H can be expressed in terms of (i) our
prior, or existing, degree of belief in H and (ii) the contribution of
newly observed evidence.
Of interest to parameter estimation, Bayes’ theorem allows us to
calculate the probability distribution of a particular variable. In
Bayesian parameter estimation, we use Bayes’ theorem to estimate the
posterior distribution of a parameter value conditioned on our data,
that is, \(P(\theta|D)\). Compared to
frequentist parameter estimation, which calculates point estimates for
parameter values, Bayesian parameter estimation gives us a new
way to quantify how uncertain we are about our parameter estimates
through the use of probability distributions.
Cognitive reappraisal
model
We will first estimate a model using the cognitive
reappraisal score as a potential moderator for the relationship
between the hours of sleep one reports on a particular
night and their reported negative affect level the
following day.
Note that we are using the brms package (Bürkner,
2017) to fit our Bayesian models. This package allows the user to
specify prior distributions for parameters. However, with a relatively
simple linear model such as this one, we can instead allow brms to
automatically select uninformative priors for the model’s
parameters.
Model equation
\[ negaff_{it} = \beta_0 + \beta_1 day_{t}
+ \beta_2 sleephours_{it} + \beta_3 reappraisal_i + \beta_4
sleephours_{it} \times reappraisal_i + u_{it}\]
Run model
bpe.reap <- brm(negaff ~ 1 + day + slphrs + erq_reap_c + slphrs:erq_reap_c
+ (1 + slphrs + erq_reap_c|id),
data = bpe_data, family = gaussian(),
iter = 2000, chains = 4, cores = 4)
## Family: gaussian
## Links: mu = identity; sigma = identity
## Formula: negaff ~ 1 + day + slphrs + erq_reap_c + slphrs:erq_reap_c + (1 + slphrs + erq_reap_c | id)
## Data: bpe_data (Number of observations: 1421)
## Draws: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
## total post-warmup draws = 4000
##
## Group-Level Effects:
## ~id (Number of levels: 190)
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
## sd(Intercept) 0.97 0.12 0.74 1.23 1.00 1522
## sd(slphrs) 0.10 0.02 0.05 0.13 1.01 452
## sd(erq_reap_c) 0.09 0.07 0.00 0.26 1.00 745
## cor(Intercept,slphrs) -0.75 0.09 -0.88 -0.54 1.00 1944
## cor(Intercept,erq_reap_c) 0.03 0.47 -0.86 0.85 1.00 2095
## cor(slphrs,erq_reap_c) -0.14 0.51 -0.93 0.86 1.00 1707
## Tail_ESS
## sd(Intercept) 2350
## sd(slphrs) 671
## sd(erq_reap_c) 1087
## cor(Intercept,slphrs) 2207
## cor(Intercept,erq_reap_c) 2432
## cor(slphrs,erq_reap_c) 2210
##
## Population-Level Effects:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept 3.25 0.13 2.99 3.51 1.00 3878 2817
## day -0.07 0.01 -0.08 -0.05 1.00 7817 2844
## slphrs -0.08 0.02 -0.11 -0.05 1.00 4169 3344
## erq_reap_c -0.01 0.12 -0.23 0.22 1.00 3821 3195
## slphrs:erq_reap_c 0.00 0.01 -0.03 0.03 1.00 3941 3073
##
## Family Specific Parameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma 0.78 0.02 0.75 0.81 1.00 2981 2621
##
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
## Estimate Est.Error Q2.5 Q97.5
## R2 0.4451373 0.01807948 0.408227 0.4794034
Interpret
results
Check model
convergence
We see that all R-hat values are \(\leq\) 1.01, which indicates good
convergence.
Assess 95% credible
intervals
Since a Bayesian model does not give us p-values like a
traditional frequentist model would, we can instead use something called
a 95% credible interval to examine statistical
significance. We receive two values for each estimated parameter: the
interval’s lower bound (l-95% CI) and the interval’s upper bound (u-95%
CI). Given the data, the probability that the true parameter lies
between these values is 0.95.
One way to evaluate a 95% credible interval is to see whether the
interval contains 0. If 0 falls within the 95% credible interval, this
suggests that the parameter may not be significant. If 0 does not fall
within the 95% credible interval, we can be reasonably sure that the
parameter is significant.
For this model, the credible intervals of day and
hours of sleep do not contain 0, suggesting significant
associations between these variables and negative
affect. However, the credible intervals of cognitive
reappraisal and the interaction between hours of
sleep and cognitive reappraisal, the
predictors we are most interested in, do contain 0. Thus, we might doubt
the significance of these parameters.
View posterior
distributions of parameters



We can generate plots to visualize the posterior distributions for
our estimated parameters. Most parameters appear relatively normally
distributed, with a few positively- and negatively-skewed
exceptions.
Visualize model
We plot the model’s predictions for negative affect
vs. hours of sleep for “high” (\(\geq\) 0) and “low” (\(<\) 0) centered cognitive
reappraisal scores.
# save model predictions to dataset
bpe_data$pred_reap <- predict(bpe.reap, newdata=bpe_data, allow_new_levels=TRUE)
# discretize reappraisal variable for plotting purposes
bpe_data$erq_reap_hl <- ifelse(bpe_data$erq_reap_c >= 0, "High", "Low")
ggplot(data = bpe_data, aes(x = slphrs, y = pred_reap[,"Estimate"],
color = erq_reap_hl)) +
geom_jitter(size = .75, width = 0.35) +
geom_smooth(method = lm) +
xlab("Hours of Sleep") +
ylab("Negative Affect") +
theme_classic() +
theme(axis.title=element_text(size=12),
axis.text=element_text(size=12),
plot.title=element_text(size=14, hjust=.5)) +
theme(text = element_text(family = "Times New Roman")) +
ggtitle("Negative Affect vs. Sleep\nfor High and Low Reappraisal Individuals") +
labs(colour = "Cognitive Reappraisal Score")

Read plot
In this visualization, each point plots an individual’s reported
negative affect on a particular day against the number
of hours of sleep they report from the prior night.
Points are color coded to indicate whether the individual has a high
(coral) or low (turquoise) cognitive reappraisal
score.
The coral regression line represents the aggregate of individuals
with high cognitive reappraisal scores, while the
turquoise regression line represents the aggregate of individuals with
low cognitive reappraisal scores. The slope of each
line indicates the strength of the association between hours of
sleep at night and negative affect the
following day for that group. We note that the coral line has a more
negative slope than the turquoise line, indicating a stronger
association between hours of sleep and negative
affect for the high cognitive reappraisal
group.
Interpret plot
We observe that having a higher cognitive
reappraisal score may predict a larger difference in
negative affect for a fixed difference in hours
of sleep. In other words, it appears that those with higher
cognitive reappraisal scores report negative
affect that is more closely related to how many hours
of sleep they got the previous night. This may suggest that
cognitive reappraisal is most effective in decreasing
negative affect when an individual has gotten
sufficient hours of sleep.
Expressive suppression
model
Next, we will estimate a very similar model to examine the
expressive suppression score as a potential moderator,
in place of the cognitive reappraisal score.
Model equation
\[ negaff_{it} = \beta_0 + \beta_1 day_{t}
+ \beta_2 sleephours_{it} + \beta_3 suppression_i + \beta_4
sleephours_{it} \times suppression_i + u_{it}\]
Run model
bpe.supp <- brm(negaff ~ 1 + day + slphrs + erq_supp_c + slphrs:erq_supp_c
+ (1 + slphrs + erq_supp_c|id),
data = bpe_data, family = gaussian(),
iter = 2000, chains = 4, cores = 4)
## Family: gaussian
## Links: mu = identity; sigma = identity
## Formula: negaff ~ 1 + day + slphrs + erq_supp_c + slphrs:erq_supp_c + (1 + slphrs + erq_supp_c | id)
## Data: bpe_data (Number of observations: 1421)
## Draws: 4 chains, each with iter = 2000; warmup = 1000; thin = 1;
## total post-warmup draws = 4000
##
## Group-Level Effects:
## ~id (Number of levels: 190)
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS
## sd(Intercept) 0.94 0.13 0.68 1.20 1.00 1085
## sd(slphrs) 0.09 0.02 0.05 0.13 1.01 468
## sd(erq_supp_c) 0.11 0.07 0.01 0.27 1.00 500
## cor(Intercept,slphrs) -0.73 0.11 -0.87 -0.46 1.00 1550
## cor(Intercept,erq_supp_c) 0.36 0.39 -0.54 0.93 1.00 1348
## cor(slphrs,erq_supp_c) -0.17 0.46 -0.90 0.77 1.00 1032
## Tail_ESS
## sd(Intercept) 1954
## sd(slphrs) 568
## sd(erq_supp_c) 925
## cor(Intercept,slphrs) 1555
## cor(Intercept,erq_supp_c) 1844
## cor(slphrs,erq_supp_c) 2053
##
## Population-Level Effects:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## Intercept 3.23 0.13 2.98 3.49 1.00 3936 2966
## day -0.07 0.01 -0.08 -0.05 1.00 10028 2715
## slphrs -0.08 0.02 -0.11 -0.05 1.00 4138 3393
## erq_supp_c 0.09 0.10 -0.12 0.28 1.00 2683 2776
## slphrs:erq_supp_c -0.01 0.01 -0.03 0.02 1.00 3047 2582
##
## Family Specific Parameters:
## Estimate Est.Error l-95% CI u-95% CI Rhat Bulk_ESS Tail_ESS
## sigma 0.78 0.02 0.75 0.81 1.00 2543 3192
##
## Draws were sampled using sampling(NUTS). For each parameter, Bulk_ESS
## and Tail_ESS are effective sample size measures, and Rhat is the potential
## scale reduction factor on split chains (at convergence, Rhat = 1).
## Estimate Est.Error Q2.5 Q97.5
## R2 0.4438745 0.01804483 0.4068929 0.4780322
Interpret
results
Check model
convergence
We see that all R-hat values are \(\leq\) 1.01, which indicates good
convergence.
Assess 95% credible
intervals
We again will use each parameter’s 95% credible
interval to assess its significance. As a reminder, the
probability, given the data, that the true parameter falls within the
credible interval is 0.95. We can evaluate a 95% credible interval by
seeing whether the interval contains 0.
For this model, the credible intervals of day and
hours of sleep do not contain 0, suggesting significant
associations between these variables and negative
affect. However, the credible intervals of expressive
suppression and the interaction between hours of
sleep and expressive suppression, the
predictors we are most interested in, do contain 0. Thus, we might doubt
the significance of these parameters.
View posterior
distributions of parameters



We can generate plots to visualize the posterior distributions for
our estimated parameters. Most parameters appear relatively normally
distributed, with a few positively- and negatively-skewed
exceptions.
Visualize model
We plot the model’s predictions for negative affect
vs. hours of sleep for “high” (\(\geq\) 0) and “low” (\(<\) 0) centered expressive
suppression scores.
# save model predictions to dataset
bpe_data$pred_supp <- predict(bpe.supp, newdata=bpe_data, allow_new_levels=TRUE)
# discretize suppression variable for plotting purposes
bpe_data$erq_supp_hl <- ifelse(bpe_data$erq_supp_c >= 0, "High", "Low")
ggplot(data = bpe_data, aes(x = slphrs, y = pred_supp[,"Estimate"],
color = erq_supp_hl)) +
geom_jitter(size = .75, width = 0.35) +
geom_smooth(method = lm) +
xlab("Hours of Sleep") +
ylab("Negative Affect") +
theme_classic() +
theme(axis.title=element_text(size=12),
axis.text=element_text(size=12),
plot.title=element_text(size=14, hjust=.5)) +
theme(text = element_text(family = "Times New Roman")) +
ggtitle("Negative Affect vs. Sleep\nfor High and Low Suppression Individuals") +
labs(colour = "Expressive Suppression Score")

Read plot
In this visualization, each point plots an individual’s reported
negative affect on a particular day against the number
of hours of sleep they report from the prior night.
Points are color coded to indicate whether the individual has a high
(coral) or low (turquoise) expressive suppression
score.
The coral regression line represents the aggregate of individuals
with high expressive suppression scores, while the
turquoise regression line represents the aggregate of individuals with
low expressive suppression scores. The slope of each
line indicates the strength of the association between hours of
sleep at night and negative affect the
following day for that group. We note that the coral line has a more
negative slope than the turquoise line, indicating a stronger
association between sleep and negative
affect for the high expressive suppression
group.
Interpret plot
We observe that having a higher expressive
suppression score may predict a larger difference in
negative affect for a fixed difference in hours
of sleep. In other words, it appears that those with higher
expressive suppression scores report negative
affect that is more closely related to how many hours
of sleep they got the previous night. This may suggest that
expressive suppression is most effective in decreasing
negative affect when an individual has gotten
sufficient hours of sleep.
We observe that the moderating effects of cognitive
reappraisal and expressive suppression appear
similar, suggesting that a more general factor is moderating the
relationship between hours of sleep and
negative affect. We may want to investigate this
further in future work.
Model comparison
We will now use leave-one-out cross-validation (LOOCV) to compare the
relative fits of the cognitive reappraisal model and
the expressive suppression model. This type of model
comparison is typically done between two different kinds of models using
the same data. Our models have the same form but use slightly different
data (reappraisal predictor vs. suppression predictor). However, for
demonstrative purposes, we will stil compare them using LOOCV.
bpe.reap <- add_criterion(bpe.reap, c("loo"))
bpe.supp <- add_criterion(bpe.supp, c("loo"))
loo_compare(bpe.reap, bpe.supp)
## elpd_diff se_diff
## bpe.supp 0.0 0.0
## bpe.reap -1.4 1.6
We observe that the cognitive reappraisal model
appears to have a better fit than the expressive
suppression model. This indicates that the relationships among
variables in the cognitive reappraisal model are better
suited to a linear model than those in the expressive
suppression model. A LOOCV comparison would likely give us more
helpful information if we were comparing, for example, a linear version
of the cognitive reappraisal model and a nonlinear
version of the cognitive reappraisal model.
Beyond using formal quantitative techniques like LOOCV for model
comparison, it can be helpful to compare the plotted posterior
distributions of parameters across the two models. This can help us
understand the relative levels of uncertainty we have in those
models.
Conclusion
Shifting from a frequentist understanding of parameter estimation to
a Bayesian understanding can be challenging, and it is important to
consider the merits and drawbacks of both approaches. Bayesian parameter
estimation can seem unintuitive at first, but it provides us with new
tools to describe and analyze the uncertainty inherent in our data.
In social science research, being able to incorporate
subjectivity into our models can give us a new outlook on phenomena that
are often hard to pin down in a standard quantitative
framework.
Additional
resources
If you would like to learn more about the concepts mentioned in this
tutorial, here are a few external resources:
References
Bürkner, P.-C. (2017). brms: An R package for Bayesian multilevel
models using Stan. Journal of Statistical Software,
80(1). https://doi.org/10.18637/jss.v080.i01
Gross, J. J., & John, O. P. (2003). Individual differences in two
emotion regulation processes: Implications for affect, relationships,
and well-being. Journal of Personality and Social Psychology,
85(2), 348–362. https://doi.org/10.1037/0022-3514.85.2.348
Joyce, J. (2021). Bayes’ theorem (E. N. Zalta, Ed.). The Stanford
Encyclopedia of Philosophy (Fall 2021 Edition). https://plato.stanford.edu/archives/fall2021/entries/bayes-theorem/
(Original work published 2003)
Kahn, M., Sheppes, G., & Sadeh, A. (2013). Sleep and emotions:
Bidirectional links and underlying mechanisms. International Journal
of Psychophysiology, 89(2), 218–228. https://doi.org/10.1016/j.ijpsycho.2013.05.010
Ram, N., Conroy, D. E., Pincus, A. L., Hyde, A. L., & Molloy, L.
E. (2012). Tethering theory to method: Using measures of intraindividual
variability to operationalize individuals’ dynamic characteristics. In
G. Hancock & J. Harring (Eds.), Advances in longitudinal methods
in the social and behavioral sciences (pp. 81-110). New York:
Information Age.
You may now switch back to the Qualtrics survey tab. You can
leave this tab open and refer back to the tutorial as you complete the
rest of the survey.
LS0tCnRpdGxlOiAiTW9kZWxpbmcgd2l0aCB1bmNlcnRhaW50eTogQSBCYXllc2lhbiBwYXJhbWV0ZXIgZXN0aW1hdGlvbiB0dXRvcmlhbCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2RlcHRoOiA0CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRoZW1lOiBmbGF0bHkKICAgIGhpZ2hsaWdodDogdGFuZ28KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0CmVkaXRvcl9vcHRpb25zOgogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKLS0tCgo8Zm9udCBzaXplPSI0Ij4KCioqQWZ0ZXIgcmVhZGluZyB0aHJvdWdoIHRoaXMgdHV0b3JpYWwsIHlvdSBtYXkga2VlcCB0aGlzIHRhYiBvcGVuIGFuZCByZWZlciBiYWNrIHRvIHRoZSB0dXRvcmlhbCBhcyB5b3UgY29tcGxldGUgdGhlIHJlc3Qgb2YgdGhlIHN1cnZleS4qKgoKIyBJbnRyb2R1Y3Rpb24KCiMjIFRlY2huaWNhbCBvYmplY3RpdmUKTGVhcm4gdGhlIGJhc2ljcyBvZiBCYXllc2lhbiBwYXJhbWV0ZXIgZXN0aW1hdGlvbiwgYSBCYXllc2lhbiBkYXRhIGFuYWx5c2lzIHRlY2huaXF1ZSwgYW5kIGhvdyBpdCBkaWZmZXJzIGZyb20gZnJlcXVlbnRpc3QgcGFyYW1ldGVyIGVzdGltYXRpb24KCiMjIFN1YnN0YW50aXZlIHJlc2VhcmNoIHF1ZXN0aW9uCkhvdyBkbyBlbW90aW9uIHJlZ3VsYXRpb24gc3RyYXRlZ2llcyBtb2RlcmF0ZSB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiBzbGVlcCBhbmQgbmVnYXRpdmUgZW1vdGlvbnM/CgojIyBCYXllc2lhbiBwYXJhbWV0ZXIgZXN0aW1hdGlvbgpJbiB0aGlzIHR1dG9yaWFsLCB3ZSB3aWxsIGJlIGFwcGx5aW5nIHRoZSBCYXllc2lhbiBsZW5zIHRvIHRoZSBlc3RpbWF0aW9uIG9mIHBhcmFtZXRlcnMgaW4gYSBtdWx0aWxldmVsIGxpbmVhciBtb2RlbC4gSW4gKipCYXllc2lhbiBwYXJhbWV0ZXIgZXN0aW1hdGlvbioqLCB3ZSB2aWV3IHBhcmFtZXRlciBlc3RpbWF0ZXMgYXMgcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9ucywgYXMgb3Bwb3NlZCB0byBwb2ludCB2YWx1ZXMuICAKCiMjIEVtb3Rpb24gcmVndWxhdGlvbgpJbiB0aGUgZm9sbG93aW5nIEJheWVzaWFuIGRhdGEgYW5hbHlzaXMgbW9kZWxzLCB3ZSB3aWxsIGV4YW1pbmUgdHdvIGVtb3Rpb24gcmVndWxhdGlvbiBzdHJhdGVnaWVzLCAqKmNvZ25pdGl2ZSByZWFwcHJhaXNhbCoqIGFuZCAqKmV4cHJlc3NpdmUgc3VwcHJlc3Npb24qKiwgYW5kIHdoZXRoZXIgdGhleSBtb2RlcmF0ZSB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiAqKmhvdXJzIG9mIHNsZWVwKiogYXQgbmlnaHQgYW5kICoqbmVnYXRpdmUgYWZmZWN0KiogdGhlIGZvbGxvd2luZyBkYXkuCgpCcmllZmx5LCBpbiAqKmNvZ25pdGl2ZSByZWFwcHJhaXNhbCoqLCBvbmUgY2hhbmdlcyB0aGUgd2F5IGluIHdoaWNoIHRoZXkgdGhpbmsgYWJvdXQgYW4gZW1vdGlvbmFsbHktaW5kdWNpbmcgZXZlbnQgaW4gb3JkZXIgdG8gYWx0ZXIgdGhlaXIgZW1vdGlvbmFsIHJlc3BvbnNlIHRvIHRoYXQgZXZlbnQuIEZvciBleGFtcGxlLCBpbnN0ZWFkIG9mIHRoaW5raW5nIGFib3V0IGFuIGV4YW0gYXMgYSBkaWZmaWN1bHQgYW5kIGNvbnNlcXVlbnRpYWwgdGVzdCBvZiB0aGVpciBhYmlsaXRpZXMsIGEgc3R1ZGVudCBtaWdodCBjaG9vc2UgdG8gZnJhbWUgdGhlIGV4YW0gYXMgYW4gb3Bwb3J0dW5pdHkgdG8gc2hvdyB3aGF0IHRoZXkgaGF2ZSBsZWFybmVkLiBJbiAqKmV4cHJlc3NpdmUgc3VwcHJlc3Npb24qKiwgb25lIHJlZ3VsYXRlcyB0aGVpciBlbW90aW9ucyBieSBpbmhpYml0aW5nIHRoZWlyIGV4dGVybmFsIGRpc3BsYXlzIG9mIGVtb3Rpb24uIEZvciBleGFtcGxlLCBhIHN0dWRlbnQgd2hvIGZlZWxzIG5lcnZvdXMgYWJvdXQgYW4gdXBjb21pbmcgZXhhbSBtYXkgc3RvcCB0aGVtc2VsdmVzIGZyb20gc2hvd2luZyBhIHdvcnJpZWQgbG9vayBvbiB0aGVpciBmYWNlIGFuZCB0ZWxsaW5nIHRoZWlyIGZyaWVuZHMgdGhhdCB0aGV5IGZlZWwgbmVydm91cy4gTW9yZSBpbmZvcm1hdGlvbiBvbiB0aGVzZSB0d28gZW1vdGlvbiByZWd1bGF0aW9uIHN0cmF0ZWdpZXMgY2FuIGJlIGZvdW5kIGluIEdyb3NzICYgSm9obiAoMjAwMykuCgojIyBUaGUgcHJlc2VudCBzdHVkeTogRW1vdGlvbiByZWd1bGF0aW9uLCBzbGVlcCwgYW5kIG5lZ2F0aXZlIGFmZmVjdAoKSW4gb3VyIGFuYWx5c2lzLCB3ZSB3aWxsIGJlIGxvb2tpbmcgYXQgdGhlIHJlbGF0aW9uc2hpcHMgYW1vbmcgdGhlc2UgZW1vdGlvbiByZWd1bGF0aW9uIHN0cmF0ZWdpZXMsIHNsZWVwLCBhbmQgbmVnYXRpdmUgYWZmZWN0LCBhbHNvIGtub3duIGFzIG5lZ2F0aXZlIGVtb3Rpb24uIEFuIGluZGl2aWR1YWwncyBlbW90aW9uIHJlZ3VsYXRpb24gYW5kIGNvcGluZyBzdHJhdGVnaWVzIGFyZSB0aG91Z2h0IHRvIG1vZGVyYXRlIHRoZSBpbXBhY3Qgb2Ygc3RyZXNzIG9uIHNsZWVwIHF1YWxpdHkgKEthaG4gZXQgYWwuLCAyMDEzKS4gV2UgbWlnaHQgYWxzbyBiZSBpbnRlcmVzdGVkIGluIHdoZXRoZXIgZW1vdGlvbiByZWd1bGF0aW9uIHN0cmF0ZWdpZXMgbW9kZXJhdGUgdGhlIGltcGFjdCBvZiBzbGVlcCBvbiBuZWdhdGl2ZSBlbW90aW9ucyB0aGUgZm9sbG93aW5nIGRheS4gSW4gb3RoZXIgd29yZHMsICoqZG9lcyBhIHBhcnRpY3VsYXIgZW1vdGlvbiByZWd1bGF0aW9uIHN0cmF0ZWd5IGhlbHAgdXMgYmV0dGVyIG1hbmFnZSBvdXIgbmVnYXRpdmUgZW1vdGlvbnMgYWZ0ZXIgYSBuaWdodCBvZiBwb29yIHNsZWVwPyoqIAoKVGhlIGRhdGEgd2UgYXJlIHVzaW5nIGNvbWUgZnJvbSB0aGUgQU1JQiBzdHVkeSwgYSBtdWx0aXBsZSB0aW1lc2NhbGUgc3R1ZHkgb2YgY29sbGVnZSBzdHVkZW50cyAoUmFtIGV0IGFsLiwgMjAxMikuIEluIHBhcnRpY3VsYXIsIHdlIHdpbGwgYmUgbG9va2luZyBhdCBjb2xsZWdlIHN0dWRlbnRzJyBkYWlseSBzZWxmLXJlcG9ydHMgb2YgdGhlaXIgc2xlZXAgYW5kIG5lZ2F0aXZlIGFmZmVjdCBvdmVyIHRoZSBjb3Vyc2Ugb2YgZWlnaHQgZGF5cywgYXMgd2VsbCBhcyB0aGVpciBkaXNwb3NpdGlvbmFsIGNvZ25pdGl2ZSByZWFwcHJhaXNhbCBhbmQgZXhwcmVzc2l2ZSBzdXBwcmVzc2lvbiBzY29yZXMuIFRoZSBkYXRhIGNhbiBiZSBkb3dubG9hZGVkIGZyb20gaHR0cHM6Ly90aGVjaGFuZ2VsYWIuc3RhbmZvcmQuZWR1L2NvbGxhYm9yYXRpb25zL3RoZS1hbWliLWRhdGEvLiBXZSB3aWxsIHJ1biBhIHJlZ3Jlc3Npb24gYW5hbHlzaXMgdXNpbmcgdGhlc2UgZGF0YSB0byBnZXQgc29tZSBwcmVsaW1pbmFyeSBpbnNpZ2h0cyBpbnRvIHRoZSBhc3NvY2lhdGlvbnMgYW1vbmcgZW1vdGlvbiByZWd1bGF0aW9uLCBzbGVlcCwgYW5kIG5lZ2F0aXZlIGFmZmVjdC4KCiMgUHJlbGltaW5hcmllcwoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UpCnNldC5zZWVkKDEpCmBgYAoKIyMgTG9hZCBsaWJyYXJpZXMgYW5kIGRhdGEKCmBgYHtyIGxpYnJhcmllc30KbGlicmFyeShicm1zKQpsaWJyYXJ5KGxvbykKbGlicmFyeShwc3ljaCkKbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKV2UgcmVhZCBpbiB0aGUgZGF0YSBmcm9tIHRoZSBvbmxpbmUgcmVwb3NpdG9yeS4KCmBgYHtyIHBlcnNvbi1sZXZlbCBkYXRhfQojIHNldCBmaWxlcGF0aCBmb3IgZGF0YSBmaWxlCmZpbGVwYXRoIDwtCiAgImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9UaGUtQ2hhbmdlLUxhYi9jb2xsYWJvcmF0aW9ucy9tYWluL0FNSUIvQU1JQl9wZXJzb25zLmNzdiIKIyByZWFkIGluIHRoZSAuY3N2IGZpbGUgdXNpbmcgdGhlIHVybCgpIGZ1bmN0aW9uCkFNSUJfcGVyc29ucyA8LSByZWFkLmNzdihmaWxlPXVybChmaWxlcGF0aCksaGVhZGVyPVRSVUUpCmBgYAoKYGBge3IgZGF5LWxldmVsIGRhdGF9CiMgc2V0IGZpbGVwYXRoIGZvciBkYXRhIGZpbGUKZmlsZXBhdGggPC0KICAiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL1RoZS1DaGFuZ2UtTGFiL2NvbGxhYm9yYXRpb25zL21haW4vQU1JQi9BTUlCX2RhaWx5LmNzdiIKIyByZWFkIGluIHRoZSAuY3N2IGZpbGUgdXNpbmcgdGhlIHVybCgpIGZ1bmN0aW9uCkFNSUJfZGFpbHkgPC0gcmVhZC5jc3YoZmlsZT11cmwoZmlsZXBhdGgpLGhlYWRlcj1UUlVFKQpgYGAKCiMjIERhdGEgbWFuaXB1bGF0aW9uCgpXZSBtZXJnZSB0aGUgZGFpbHktbGV2ZWwgdmFyaWFibGVzICgqKnBhcnRpY2lwYW50IElEKiosICoqZGF5KiosICoqaG91cnMgb2Ygc2xlZXAqKiwgYW5kICoqbmVnYXRpdmUgYWZmZWN0KiopIGFuZCB0aGUgcGVyc29uLWxldmVsIHZhcmlhYmxlcyAoKipwYXJ0aWNpcGFudCBJRCoqLCAqKmNvZ25pdGl2ZSByZWFwcHJhaXNhbCoqIHNjb3JlLCAqKmV4cHJlc3NpdmUgc3VwcHJlc3Npb24qKiBzY29yZSkgaW50byBhIHNpbmdsZSBkYXRhc2V0LgoKYGBge3IgZm9ybWF0IGRhdGF9CiMgc3Vic2V0IHRvIGRheS1sZXZlbCB2YXJpYWJsZXMgb2YgaW50ZXJlc3QKYnBlX2RhaWx5IDwtIEFNSUJfZGFpbHlbLGMoImlkIiwgImRheSIsICJzbHBocnMiLCAibmVnYWZmIildCiMgc3Vic2V0IHRvIHBlcnNvbi1sZXZlbCB2YXJpYWJsZXMgb2YgaW50ZXJlc3QKYnBlX3BlcnNvbnMgPC0gQU1JQl9wZXJzb25zWyxjKCJpZCIsICJlcnFfcmVhcCIsICJlcnFfc3VwcCIpXQojIG1lcmdlIGRheS0gYW5kIHBlcnNvbi1sZXZlbCBkYXRhCmJwZV9kYXRhIDwtIG1lcmdlKGJwZV9kYWlseSwgYnBlX3BlcnNvbnMsIGJ5ID0gImlkIikKYGBgCgpXZSBjZW50ZXIgdGhlIGVtb3Rpb24gcmVndWxhdGlvbiBxdWVzdGlvbm5haXJlIHNjb3JlcyB0byBmYWNpbGl0YXRlIHRoZSBpbnRlcnByZXRhdGlvbiBvZiBtb2RlbCByZXN1bHRzLgoKYGBge3IgY2VudGVyIHByZWRpY3Rvcn0KIyBjZW50ZXIgdGhlIGVycSBzdWJzY2FsZSBzY29yZSB2YXJpYWJsZXMgZm9yIGludGVycHJldGFiaWxpdHkKYnBlX2RhdGEkZXJxX3JlYXBfYyA8LSBzY2FsZShicGVfZGF0YSRlcnFfcmVhcCwgY2VudGVyPVRSVUUsc2NhbGU9RkFMU0UpWywxXQpicGVfZGF0YSRlcnFfc3VwcF9jIDwtIHNjYWxlKGJwZV9kYXRhJGVycV9zdXBwLCBjZW50ZXI9VFJVRSxzY2FsZT1GQUxTRSlbLDFdCmBgYAoKIyBJbml0aWFsIHBsb3RzCgpCZWZvcmUgcnVubmluZyBvdXIgbW9kZWxzLCBpdCBjYW4gYmUgaGVscGZ1bCB0byBleGFtaW5lIHRoZSByYXcgZGF0YS4KCiMjIENvcnJlbGF0aW9ucyBhbmQgZGlzdHJpYnV0aW9ucwoKYGBge3IgcGxvdCBjb3JyZWxhdGlvbnN9CiMgY2FsY3VsYXRlIGNvcnJlbGF0aW9ucwogICMgZHJvcHBpbmcgdGhlIGlkIGFuZCBub24tY2VudGVyZWQgZXJxIGNvbHVtbnMKY29yKGJwZV9kYXRhWyAsYygtMSwgLTUsIC02KV0sIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQojIHBsb3QgY29ycmVsYXRpb25zCnBhaXJzLnBhbmVscyhicGVfZGF0YVsgLGMoLTEsIC01LCAtNildKQpgYGAKCldlIHNlZSByZWxhdGl2ZWx5IHdlYWsgY29ycmVsYXRpb25zIG92ZXJhbGwsIGJ1dCBub3RlIGEgc21hbGwgbmVnYXRpdmUgY29ycmVsYXRpb24gYmV0d2VlbiAqKmhvdXJzIG9mIHNsZWVwKiogYW5kICoqbmVnYXRpdmUgYWZmZWN0KiogKC0wLjE2KSwgYXMgd2VsbCBhcyBhIHNtYWxsIG5lZ2F0aXZlIGNvcnJlbGF0aW9uIGJldHdlZW4gKipjb2duaXRpdmUgcmVhcHByYWlzYWwqKiBhbmQgKipleHByZXNzaXZlIHN1cHByZXNzaW9uKiogKC0wLjEzKS4gV2UgYWxzbyBvYnNlcnZlIGEgc21hbGwgbmVnYXRpdmUgY29ycmVsYXRpb24gYmV0d2VlbiAqKmRheSoqIGluIHN0dWR5IGFuZCAqKm5lZ2F0aXZlIGFmZmVjdCoqICgtMC4xNCkuCgpUaGUgZGlzdHJpYnV0aW9ucyBvZiB0aGUgdmFyaWFibGVzIGNhbiBiZSBzZWVuIG9uIHRoZSBkaWFnb25hbC4gT2YgcGFydGljdWxhciBpbnRlcmVzdCwgd2Ugbm90ZSB0aGF0IHRoZSBkaXN0cmlidXRpb24gb2YgKipjb2duaXRpdmUgcmVhcHByYWlzYWwqKiBzY29yZXMgaGFzIGEgbmVnYXRpdmUgc2tldywgd2hpbGUgdGhlIGRpc3RyaWJ1dGlvbiBvZiAqKmV4cHJlc3NpdmUgc3VwcHJlc3Npb24qKiBzY29yZXMgaXMgcmVsYXRpdmVseSBzeW1tZXRyaWNhbC4KCiMjIExpbmVhciByZWdyZXNzaW9uOiBOZWdhdGl2ZSBhZmZlY3QgdnMuIGhvdXJzIG9mIHNsZWVwCgpXZSB3aWxsIG5vdyBwbG90IGEgc2ltcGxlLCBub24tQmF5ZXNpYW4gbGluZWFyIHJlZ3Jlc3Npb24gb2YgKipuZWdhdGl2ZSBhZmZlY3QqKiB2cy4gKipob3VycyBvZiBzbGVlcCoqIHRvIGdldCBhIGJldHRlciBzZW5zZSBvZiB0aGUgYXNzb2NpYXRpb24gYmV0d2VlbiBvdXIgb3V0Y29tZSB2YXJpYWJsZSBhbmQgb3VyIG1haW4gcHJlZGljdG9yIHZhcmlhYmxlLgoKYGBge3IgbmVnYWZmIHZzLiBzbHBocnN9CmdncGxvdChkYXRhPWJwZV9kYXRhLCBhZXMoeD1zbHBocnMsIHk9bmVnYWZmKSkgKwogIGdlb21faml0dGVyKHdpZHRoID0gMC4zNSkgKwogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgbHR5PTEsIHNpemU9MikgKwogIHhsYWIoIkhvdXJzIG9mIFNsZWVwIikgKyB5bGFiKCJOZWdhdGl2ZSBBZmZlY3QgTGV2ZWwiKSArCiAgdGhlbWVfY2xhc3NpYygpICArCiAgdGhlbWUoYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMiksCiAgICAgICAgYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgICAgICBwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE0LCBoanVzdD0uNSkpICsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJUaW1lcyBOZXcgUm9tYW4iKSkgKwogIGdndGl0bGUoIk5lZ2F0aXZlIEFmZmVjdCB2cy4gU2xlZXAiKQpgYGAKCkluIGdlbmVyYWwsIG1vcmUgKipob3VycyBvZiBzbGVlcCoqIGlzIGFzc29jaWF0ZWQgd2l0aCBsb3dlciAqKm5lZ2F0aXZlIGFmZmVjdCoqLiBIb3dldmVyLCBtYW55IG9mIHRoZSBzbGVlcCBkdXJhdGlvbnMgY29ycmVzcG9uZCB0byBhIHdpZGUgcmFuZ2Ugb2YgKipuZWdhdGl2ZSBhZmZlY3QqKiB2YWx1ZXMsIHN1Z2dlc3RpbmcgZGlmZmVyZW5jZXMgaW4gKipuZWdhdGl2ZSBhZmZlY3QqKiBhY3Jvc3MgaW5kaXZpZHVhbHMuCgojIFRoZSBCYXllc2lhbiBhcHByb2FjaAoKIyMgQmF5ZXMnIHRoZW9yZW0KCkJlZm9yZSBydW5uaW5nIG91ciBCYXllc2lhbiBtb2RlbHMsIHdlIHdpbGwgYnJpZWZseSByZWNhcCBCYXllcycgdGhlb3JlbS4gQmF5ZXMnIHRoZW9yZW0gZ2l2ZXMgdXMgYSBtYXRoZW1hdGljYWwgZXhwcmVzc2lvbiBmb3IgdGhlIHByb2JhYmlsaXR5IG9mIGEgaHlwb3RoZXNpcywgSCwgY29uZGl0aW9uYWwgb24gKHRoYXQgaXMsIGdpdmVuIGV4aXN0aW5nIGtub3dsZWRnZSBvZikgYSBib2R5IG9mIGV2aWRlbmNlLCBFIChKb3ljZSwgMjAwMy8yMDIxKS4gVGhlIGV4cHJlc3Npb24gZm9yIEJheWVz4oCZIHRoZW9yZW0gaXMKCiQkIFAoSHxFKT0gXGZyYWN7UChFfEgpUChIKX17UChFKX0uICQkClRoZSBwb3N0ZXJpb3IsICRQKEh8RSkkLCByZWZlcnMgdG8gdGhlIHByb2JhYmlsaXR5IG9mIHRoZSBoeXBvdGhlc2lzIGJlaW5nIHRydWUgYWZ0ZXIgaGF2aW5nIG9ic2VydmVkIHRoZSBldmlkZW5jZS4gVGhlIGxpa2VsaWhvb2QsICRQKEV8SCkkLCByZWZlcnMgdG8gdGhlIHByb2JhYmlsaXR5IG9mIG9ic2VydmluZyB0aGUgZXZpZGVuY2UgaW4gdGhlIGNhc2Ugd2hlcmUgdGhlIGh5cG90aGVzaXMgaXMgYWxyZWFkeSB0cnVlLiBUaGUgcHJpb3IsICRQKEgpJCwgcmVmZXJzIHRvIHRoZSBwcm9iYWJpbGl0eSBvZiB0aGUgaHlwb3RoZXNpcyBiZWluZyB0cnVlIHdpdGhvdXQgaGF2aW5nIG9ic2VydmVkIGFueSBldmlkZW5jZS4gRmluYWxseSwgdGhlIG5vcm1hbGl6aW5nIGNvbnN0YW50LCAkUChFKSQsIHJlZmVycyB0byB0aGUgcHJvYmFiaWxpdHkgb2YgdGhlIGV2aWRlbmNlIG9jY3VycmluZyBpbmRlcGVuZGVudCBvZiBhbnkgaHlwb3RoZXNpcy4KCiMjIEJheWVzaWFuIGludGVycHJldGF0aW9uCgpJbiBnZW5lcmFsLCBCYXllc+KAmSB0aGVvcmVtIG9wZXJhdGVzIHVuZGVyIHRoZSBhc3N1bXB0aW9uIHRoYXQgb3VyIHJlZmluZWQgZGVncmVlIG9mIGJlbGllZiBpbiBIIGNhbiBiZSBleHByZXNzZWQgaW4gdGVybXMgb2YgKGkpIG91ciBwcmlvciwgb3IgZXhpc3RpbmcsIGRlZ3JlZSBvZiBiZWxpZWYgaW4gSCBhbmQgKGlpKSB0aGUgY29udHJpYnV0aW9uIG9mIG5ld2x5IG9ic2VydmVkIGV2aWRlbmNlLgoKT2YgaW50ZXJlc3QgdG8gcGFyYW1ldGVyIGVzdGltYXRpb24sIEJheWVzJyB0aGVvcmVtIGFsbG93cyB1cyB0byBjYWxjdWxhdGUgdGhlIHByb2JhYmlsaXR5IGRpc3RyaWJ1dGlvbiBvZiBhIHBhcnRpY3VsYXIgdmFyaWFibGUuIEluIEJheWVzaWFuIHBhcmFtZXRlciBlc3RpbWF0aW9uLCB3ZSB1c2UgQmF5ZXMnIHRoZW9yZW0gdG8gZXN0aW1hdGUgdGhlIHBvc3RlcmlvciBkaXN0cmlidXRpb24gb2YgYSBwYXJhbWV0ZXIgdmFsdWUgY29uZGl0aW9uZWQgb24gb3VyIGRhdGEsIHRoYXQgaXMsICRQKFx0aGV0YXxEKSQuIENvbXBhcmVkIHRvIGZyZXF1ZW50aXN0IHBhcmFtZXRlciBlc3RpbWF0aW9uLCB3aGljaCBjYWxjdWxhdGVzIHBvaW50IGVzdGltYXRlcyBmb3IgcGFyYW1ldGVyIHZhbHVlcywgKipCYXllc2lhbiBwYXJhbWV0ZXIgZXN0aW1hdGlvbiBnaXZlcyB1cyBhIG5ldyB3YXkgdG8gcXVhbnRpZnkgaG93IHVuY2VydGFpbiB3ZSBhcmUgYWJvdXQgb3VyIHBhcmFtZXRlciBlc3RpbWF0ZXMgdGhyb3VnaCB0aGUgdXNlIG9mIHByb2JhYmlsaXR5IGRpc3RyaWJ1dGlvbnMuKioKCiMgQ29nbml0aXZlIHJlYXBwcmFpc2FsIG1vZGVsCgpXZSB3aWxsIGZpcnN0IGVzdGltYXRlIGEgbW9kZWwgdXNpbmcgdGhlICoqY29nbml0aXZlIHJlYXBwcmFpc2FsKiogc2NvcmUgYXMgYSBwb3RlbnRpYWwgbW9kZXJhdG9yIGZvciB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlICoqaG91cnMgb2Ygc2xlZXAqKiBvbmUgcmVwb3J0cyBvbiBhIHBhcnRpY3VsYXIgbmlnaHQgYW5kIHRoZWlyIHJlcG9ydGVkICoqbmVnYXRpdmUgYWZmZWN0KiogbGV2ZWwgdGhlIGZvbGxvd2luZyBkYXkuCgpOb3RlIHRoYXQgd2UgYXJlIHVzaW5nIHRoZSAqKmJybXMqKiBwYWNrYWdlIChCw7xya25lciwgMjAxNykgdG8gZml0IG91ciBCYXllc2lhbiBtb2RlbHMuIFRoaXMgcGFja2FnZSBhbGxvd3MgdGhlIHVzZXIgdG8gc3BlY2lmeSBwcmlvciBkaXN0cmlidXRpb25zIGZvciBwYXJhbWV0ZXJzLiBIb3dldmVyLCB3aXRoIGEgcmVsYXRpdmVseSBzaW1wbGUgbGluZWFyIG1vZGVsIHN1Y2ggYXMgdGhpcyBvbmUsIHdlIGNhbiBpbnN0ZWFkIGFsbG93IGJybXMgdG8gYXV0b21hdGljYWxseSBzZWxlY3QgdW5pbmZvcm1hdGl2ZSBwcmlvcnMgZm9yIHRoZSBtb2RlbCdzIHBhcmFtZXRlcnMuCgojIyBNb2RlbCBlcXVhdGlvbgoKJCQgbmVnYWZmX3tpdH0gPSBcYmV0YV8wICsgXGJldGFfMSBkYXlfe3R9ICsgXGJldGFfMiBzbGVlcGhvdXJzX3tpdH0gKyBcYmV0YV8zIHJlYXBwcmFpc2FsX2kgKyBcYmV0YV80IHNsZWVwaG91cnNfe2l0fSBcdGltZXMgcmVhcHByYWlzYWxfaSArIHVfe2l0fSQkCgojIyBSdW4gbW9kZWwKCmBgYHtyIGJwZSBtb2RlbCByZWFwLCByZXN1bHRzPSdoaWRlJ30KYnBlLnJlYXAgPC0gYnJtKG5lZ2FmZiB+IDEgKyBkYXkgKyBzbHBocnMgKyBlcnFfcmVhcF9jICsgc2xwaHJzOmVycV9yZWFwX2MKICAgICAgICAgICAgICAgICsgKDEgKyBzbHBocnMgKyBlcnFfcmVhcF9jfGlkKSwKICAgICAgICAgICAgICAgIGRhdGEgPSBicGVfZGF0YSwgZmFtaWx5ID0gZ2F1c3NpYW4oKSwKICAgICAgICAgICAgICAgIGl0ZXIgPSAyMDAwLCBjaGFpbnMgPSA0LCBjb3JlcyA9IDQpCmBgYAoKYGBge3IgYnBlIG1vZGVsIHJlYXAgc3VtfQpzdW1tYXJ5KGJwZS5yZWFwKQpiYXllc19SMihicGUucmVhcCkKYGBgCgojIyBJbnRlcnByZXQgcmVzdWx0cwoKIyMjIENoZWNrIG1vZGVsIGNvbnZlcmdlbmNlCgpXZSBzZWUgdGhhdCBhbGwgUi1oYXQgdmFsdWVzIGFyZSAkXGxlcSQgMS4wMSwgd2hpY2ggaW5kaWNhdGVzIGdvb2QgY29udmVyZ2VuY2UuCgojIyMgQXNzZXNzIDk1JSBjcmVkaWJsZSBpbnRlcnZhbHMKClNpbmNlIGEgQmF5ZXNpYW4gbW9kZWwgZG9lcyBub3QgZ2l2ZSB1cyAqcCotdmFsdWVzIGxpa2UgYSB0cmFkaXRpb25hbCBmcmVxdWVudGlzdCBtb2RlbCB3b3VsZCwgd2UgY2FuIGluc3RlYWQgdXNlIHNvbWV0aGluZyBjYWxsZWQgYSAqKjk1JSBjcmVkaWJsZSBpbnRlcnZhbCoqIHRvIGV4YW1pbmUgc3RhdGlzdGljYWwgc2lnbmlmaWNhbmNlLiBXZSByZWNlaXZlIHR3byB2YWx1ZXMgZm9yIGVhY2ggZXN0aW1hdGVkIHBhcmFtZXRlcjogdGhlIGludGVydmFsJ3MgbG93ZXIgYm91bmQgKGwtOTUlIENJKSBhbmQgdGhlIGludGVydmFsJ3MgdXBwZXIgYm91bmQgKHUtOTUlIENJKS4gR2l2ZW4gdGhlIGRhdGEsIHRoZSBwcm9iYWJpbGl0eSB0aGF0IHRoZSB0cnVlIHBhcmFtZXRlciBsaWVzIGJldHdlZW4gdGhlc2UgdmFsdWVzIGlzIDAuOTUuCgpPbmUgd2F5IHRvIGV2YWx1YXRlIGEgOTUlIGNyZWRpYmxlIGludGVydmFsIGlzIHRvIHNlZSB3aGV0aGVyIHRoZSBpbnRlcnZhbCBjb250YWlucyAwLiBJZiAwIGZhbGxzIHdpdGhpbiB0aGUgOTUlIGNyZWRpYmxlIGludGVydmFsLCB0aGlzIHN1Z2dlc3RzIHRoYXQgdGhlIHBhcmFtZXRlciBtYXkgbm90IGJlIHNpZ25pZmljYW50LiBJZiAwIGRvZXMgbm90IGZhbGwgd2l0aGluIHRoZSA5NSUgY3JlZGlibGUgaW50ZXJ2YWwsIHdlIGNhbiBiZSByZWFzb25hYmx5IHN1cmUgdGhhdCB0aGUgcGFyYW1ldGVyIGlzIHNpZ25pZmljYW50LgoKRm9yIHRoaXMgbW9kZWwsIHRoZSBjcmVkaWJsZSBpbnRlcnZhbHMgb2YgICoqZGF5KiogYW5kICoqaG91cnMgb2Ygc2xlZXAqKiBkbyBub3QgY29udGFpbiAwLCBzdWdnZXN0aW5nIHNpZ25pZmljYW50IGFzc29jaWF0aW9ucyBiZXR3ZWVuIHRoZXNlIHZhcmlhYmxlcyBhbmQgKipuZWdhdGl2ZSBhZmZlY3QqKi4gSG93ZXZlciwgdGhlIGNyZWRpYmxlIGludGVydmFscyBvZiAqKmNvZ25pdGl2ZSByZWFwcHJhaXNhbCoqIGFuZCB0aGUgaW50ZXJhY3Rpb24gYmV0d2VlbiAqKmhvdXJzIG9mIHNsZWVwKiogYW5kICoqY29nbml0aXZlIHJlYXBwcmFpc2FsKiosIHRoZSBwcmVkaWN0b3JzIHdlIGFyZSBtb3N0IGludGVyZXN0ZWQgaW4sIGRvIGNvbnRhaW4gMC4gVGh1cywgd2UgbWlnaHQgZG91YnQgdGhlIHNpZ25pZmljYW5jZSBvZiB0aGVzZSBwYXJhbWV0ZXJzLgoKIyMjIFZpZXcgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbnMgb2YgcGFyYW1ldGVycwoKYGBge3IgYnBlIG1vZGVsIHJlYXAgcG9zdH0KcGxvdChicGUucmVhcCkKYGBgCgpXZSBjYW4gZ2VuZXJhdGUgcGxvdHMgdG8gdmlzdWFsaXplIHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9ucyBmb3Igb3VyIGVzdGltYXRlZCBwYXJhbWV0ZXJzLiBNb3N0IHBhcmFtZXRlcnMgYXBwZWFyIHJlbGF0aXZlbHkgbm9ybWFsbHkgZGlzdHJpYnV0ZWQsIHdpdGggYSBmZXcgcG9zaXRpdmVseS0gYW5kIG5lZ2F0aXZlbHktc2tld2VkIGV4Y2VwdGlvbnMuCgojIyBWaXN1YWxpemUgbW9kZWwKCldlIHBsb3QgdGhlIG1vZGVsJ3MgcHJlZGljdGlvbnMgZm9yICoqbmVnYXRpdmUgYWZmZWN0KiogdnMuICoqaG91cnMgb2Ygc2xlZXAqKiBmb3IgImhpZ2giICgkXGdlcSQgMCkgYW5kICJsb3ciICgkPCQgMCkgY2VudGVyZWQgKipjb2duaXRpdmUgcmVhcHByYWlzYWwqKiBzY29yZXMuCgpgYGB7ciBicGUgbW9kZWwgcmVhcCBwbG90fQojIHNhdmUgbW9kZWwgcHJlZGljdGlvbnMgdG8gZGF0YXNldApicGVfZGF0YSRwcmVkX3JlYXAgPC0gcHJlZGljdChicGUucmVhcCwgbmV3ZGF0YT1icGVfZGF0YSwgYWxsb3dfbmV3X2xldmVscz1UUlVFKQojIGRpc2NyZXRpemUgcmVhcHByYWlzYWwgdmFyaWFibGUgZm9yIHBsb3R0aW5nIHB1cnBvc2VzCmJwZV9kYXRhJGVycV9yZWFwX2hsIDwtIGlmZWxzZShicGVfZGF0YSRlcnFfcmVhcF9jID49IDAsICJIaWdoIiwgIkxvdyIpCgpnZ3Bsb3QoZGF0YSA9IGJwZV9kYXRhLCBhZXMoeCA9IHNscGhycywgeSA9IHByZWRfcmVhcFssIkVzdGltYXRlIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGVycV9yZWFwX2hsKSkgKwogIGdlb21faml0dGVyKHNpemUgPSAuNzUsIHdpZHRoID0gMC4zNSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9IGxtKSArCiAgeGxhYigiSG91cnMgb2YgU2xlZXAiKSArCiAgeWxhYigiTmVnYXRpdmUgQWZmZWN0IikgKwogIHRoZW1lX2NsYXNzaWMoKSAgKwogIHRoZW1lKGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgICAgIGF4aXMudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMiksCiAgICAgICAgcGxvdC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xNCwgaGp1c3Q9LjUpKSArCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiVGltZXMgTmV3IFJvbWFuIikpICsKICBnZ3RpdGxlKCJOZWdhdGl2ZSBBZmZlY3QgdnMuIFNsZWVwXG5mb3IgSGlnaCBhbmQgTG93IFJlYXBwcmFpc2FsIEluZGl2aWR1YWxzIikgKwogIGxhYnMoY29sb3VyID0gIkNvZ25pdGl2ZSBSZWFwcHJhaXNhbCBTY29yZSIpCmBgYAoKIyMjIFJlYWQgcGxvdAoKSW4gdGhpcyB2aXN1YWxpemF0aW9uLCBlYWNoIHBvaW50IHBsb3RzIGFuIGluZGl2aWR1YWwncyByZXBvcnRlZCAqKm5lZ2F0aXZlIGFmZmVjdCoqIG9uIGEgcGFydGljdWxhciBkYXkgYWdhaW5zdCB0aGUgbnVtYmVyIG9mICoqaG91cnMgb2Ygc2xlZXAqKiB0aGV5IHJlcG9ydCBmcm9tIHRoZSBwcmlvciBuaWdodC4gUG9pbnRzIGFyZSBjb2xvciBjb2RlZCB0byBpbmRpY2F0ZSB3aGV0aGVyIHRoZSBpbmRpdmlkdWFsIGhhcyBhIGhpZ2ggKGNvcmFsKSBvciBsb3cgKHR1cnF1b2lzZSkgKipjb2duaXRpdmUgcmVhcHByYWlzYWwqKiBzY29yZS4KClRoZSBjb3JhbCByZWdyZXNzaW9uIGxpbmUgcmVwcmVzZW50cyB0aGUgYWdncmVnYXRlIG9mIGluZGl2aWR1YWxzIHdpdGggaGlnaCAqKmNvZ25pdGl2ZSByZWFwcHJhaXNhbCoqIHNjb3Jlcywgd2hpbGUgdGhlIHR1cnF1b2lzZSByZWdyZXNzaW9uIGxpbmUgcmVwcmVzZW50cyB0aGUgYWdncmVnYXRlIG9mIGluZGl2aWR1YWxzIHdpdGggbG93ICoqY29nbml0aXZlIHJlYXBwcmFpc2FsKiogc2NvcmVzLiBUaGUgc2xvcGUgb2YgZWFjaCBsaW5lIGluZGljYXRlcyB0aGUgc3RyZW5ndGggb2YgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gKipob3VycyBvZiBzbGVlcCoqIGF0IG5pZ2h0IGFuZCAqKm5lZ2F0aXZlIGFmZmVjdCoqIHRoZSBmb2xsb3dpbmcgZGF5IGZvciB0aGF0IGdyb3VwLiBXZSBub3RlIHRoYXQgdGhlIGNvcmFsIGxpbmUgaGFzIGEgbW9yZSBuZWdhdGl2ZSBzbG9wZSB0aGFuIHRoZSB0dXJxdW9pc2UgbGluZSwgaW5kaWNhdGluZyBhIHN0cm9uZ2VyIGFzc29jaWF0aW9uIGJldHdlZW4gKipob3VycyBvZiBzbGVlcCoqIGFuZCAqKm5lZ2F0aXZlIGFmZmVjdCoqIGZvciB0aGUgaGlnaCAqKmNvZ25pdGl2ZSByZWFwcHJhaXNhbCoqIGdyb3VwLgoKIyMjIEludGVycHJldCBwbG90CgpXZSBvYnNlcnZlIHRoYXQgaGF2aW5nIGEgaGlnaGVyICoqY29nbml0aXZlIHJlYXBwcmFpc2FsKiogc2NvcmUgbWF5IHByZWRpY3QgYSBsYXJnZXIgZGlmZmVyZW5jZSBpbiAqKm5lZ2F0aXZlIGFmZmVjdCoqIGZvciBhIGZpeGVkIGRpZmZlcmVuY2UgaW4gKipob3VycyBvZiBzbGVlcCoqLiBJbiBvdGhlciB3b3JkcywgaXQgYXBwZWFycyB0aGF0IHRob3NlIHdpdGggaGlnaGVyICoqY29nbml0aXZlIHJlYXBwcmFpc2FsKiogc2NvcmVzIHJlcG9ydCAqKm5lZ2F0aXZlIGFmZmVjdCoqIHRoYXQgaXMgbW9yZSBjbG9zZWx5IHJlbGF0ZWQgdG8gaG93IG1hbnkgKipob3VycyBvZiBzbGVlcCoqIHRoZXkgZ290IHRoZSBwcmV2aW91cyBuaWdodC4gVGhpcyBtYXkgc3VnZ2VzdCB0aGF0ICoqY29nbml0aXZlIHJlYXBwcmFpc2FsKiogaXMgbW9zdCBlZmZlY3RpdmUgaW4gZGVjcmVhc2luZyAqKm5lZ2F0aXZlIGFmZmVjdCoqIHdoZW4gYW4gaW5kaXZpZHVhbCBoYXMgZ290dGVuIHN1ZmZpY2llbnQgKipob3VycyBvZiBzbGVlcCoqLgoKIyBFeHByZXNzaXZlIHN1cHByZXNzaW9uIG1vZGVsCgpOZXh0LCB3ZSB3aWxsIGVzdGltYXRlIGEgdmVyeSBzaW1pbGFyIG1vZGVsIHRvIGV4YW1pbmUgdGhlICoqZXhwcmVzc2l2ZSBzdXBwcmVzc2lvbioqIHNjb3JlIGFzIGEgcG90ZW50aWFsIG1vZGVyYXRvciwgaW4gcGxhY2Ugb2YgdGhlICoqY29nbml0aXZlIHJlYXBwcmFpc2FsKiogc2NvcmUuCgojIyBNb2RlbCBlcXVhdGlvbgoKJCQgbmVnYWZmX3tpdH0gPSBcYmV0YV8wICsgXGJldGFfMSBkYXlfe3R9ICsgXGJldGFfMiBzbGVlcGhvdXJzX3tpdH0gKyBcYmV0YV8zIHN1cHByZXNzaW9uX2kgKyBcYmV0YV80IHNsZWVwaG91cnNfe2l0fSBcdGltZXMgc3VwcHJlc3Npb25faSArIHVfe2l0fSQkCgojIyBSdW4gbW9kZWwKCmBgYHtyIGJwZSBtb2RlbCBzdXBwLCByZXN1bHRzPSdoaWRlJ30KYnBlLnN1cHAgPC0gYnJtKG5lZ2FmZiB+IDEgKyBkYXkgKyBzbHBocnMgKyBlcnFfc3VwcF9jICsgc2xwaHJzOmVycV9zdXBwX2MKICAgICAgICAgICAgICAgICsgKDEgKyBzbHBocnMgKyBlcnFfc3VwcF9jfGlkKSwKICAgICAgICAgICAgICAgIGRhdGEgPSBicGVfZGF0YSwgZmFtaWx5ID0gZ2F1c3NpYW4oKSwKICAgICAgICAgICAgICAgIGl0ZXIgPSAyMDAwLCBjaGFpbnMgPSA0LCBjb3JlcyA9IDQpCmBgYAoKYGBge3IgYnBlIG1vZGVsIHN1cHAgc3VtfQpzdW1tYXJ5KGJwZS5zdXBwKQpiYXllc19SMihicGUuc3VwcCkKYGBgCgojIyBJbnRlcnByZXQgcmVzdWx0cwoKIyMjIENoZWNrIG1vZGVsIGNvbnZlcmdlbmNlCgpXZSBzZWUgdGhhdCBhbGwgUi1oYXQgdmFsdWVzIGFyZSAkXGxlcSQgMS4wMSwgd2hpY2ggaW5kaWNhdGVzIGdvb2QgY29udmVyZ2VuY2UuCgojIyMgQXNzZXNzIDk1JSBjcmVkaWJsZSBpbnRlcnZhbHMKCldlIGFnYWluIHdpbGwgdXNlIGVhY2ggcGFyYW1ldGVyJ3MgKio5NSUgY3JlZGlibGUgaW50ZXJ2YWwqKiB0byBhc3Nlc3MgaXRzIHNpZ25pZmljYW5jZS4gQXMgYSByZW1pbmRlciwgdGhlIHByb2JhYmlsaXR5LCBnaXZlbiB0aGUgZGF0YSwgdGhhdCB0aGUgdHJ1ZSBwYXJhbWV0ZXIgZmFsbHMgd2l0aGluIHRoZSBjcmVkaWJsZSBpbnRlcnZhbCBpcyAwLjk1LiBXZSBjYW4gZXZhbHVhdGUgYSA5NSUgY3JlZGlibGUgaW50ZXJ2YWwgYnkgc2VlaW5nIHdoZXRoZXIgdGhlIGludGVydmFsIGNvbnRhaW5zIDAuCgpGb3IgdGhpcyBtb2RlbCwgdGhlIGNyZWRpYmxlIGludGVydmFscyBvZiAgKipkYXkqKiBhbmQgKipob3VycyBvZiBzbGVlcCoqIGRvIG5vdCBjb250YWluIDAsIHN1Z2dlc3Rpbmcgc2lnbmlmaWNhbnQgYXNzb2NpYXRpb25zIGJldHdlZW4gdGhlc2UgdmFyaWFibGVzIGFuZCAqKm5lZ2F0aXZlIGFmZmVjdCoqLiBIb3dldmVyLCB0aGUgY3JlZGlibGUgaW50ZXJ2YWxzIG9mICoqZXhwcmVzc2l2ZSBzdXBwcmVzc2lvbioqIGFuZCB0aGUgaW50ZXJhY3Rpb24gYmV0d2VlbiAqKmhvdXJzIG9mIHNsZWVwKiogYW5kICoqZXhwcmVzc2l2ZSBzdXBwcmVzc2lvbioqLCB0aGUgcHJlZGljdG9ycyB3ZSBhcmUgbW9zdCBpbnRlcmVzdGVkIGluLCBkbyBjb250YWluIDAuIFRodXMsIHdlIG1pZ2h0IGRvdWJ0IHRoZSBzaWduaWZpY2FuY2Ugb2YgdGhlc2UgcGFyYW1ldGVycy4KCiMjIyBWaWV3IHBvc3RlcmlvciBkaXN0cmlidXRpb25zIG9mIHBhcmFtZXRlcnMKCmBgYHtyIGJwZSBtb2RlbCBzdXBwIHBvc3R9CnBsb3QoYnBlLnN1cHApCmBgYAoKV2UgY2FuIGdlbmVyYXRlIHBsb3RzIHRvIHZpc3VhbGl6ZSB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbnMgZm9yIG91ciBlc3RpbWF0ZWQgcGFyYW1ldGVycy4gTW9zdCBwYXJhbWV0ZXJzIGFwcGVhciByZWxhdGl2ZWx5IG5vcm1hbGx5IGRpc3RyaWJ1dGVkLCB3aXRoIGEgZmV3IHBvc2l0aXZlbHktIGFuZCBuZWdhdGl2ZWx5LXNrZXdlZCBleGNlcHRpb25zLgoKIyMgVmlzdWFsaXplIG1vZGVsCgpXZSBwbG90IHRoZSBtb2RlbCdzIHByZWRpY3Rpb25zIGZvciAqKm5lZ2F0aXZlIGFmZmVjdCoqIHZzLiAqKmhvdXJzIG9mIHNsZWVwKiogZm9yICJoaWdoIiAoJFxnZXEkIDApIGFuZCAibG93IiAoJDwkIDApIGNlbnRlcmVkICoqZXhwcmVzc2l2ZSBzdXBwcmVzc2lvbioqIHNjb3Jlcy4KCmBgYHtyIGJwZSBtb2RlbCBzdXBwIHBsb3R9CiMgc2F2ZSBtb2RlbCBwcmVkaWN0aW9ucyB0byBkYXRhc2V0CmJwZV9kYXRhJHByZWRfc3VwcCA8LSBwcmVkaWN0KGJwZS5zdXBwLCBuZXdkYXRhPWJwZV9kYXRhLCBhbGxvd19uZXdfbGV2ZWxzPVRSVUUpCiMgZGlzY3JldGl6ZSBzdXBwcmVzc2lvbiB2YXJpYWJsZSBmb3IgcGxvdHRpbmcgcHVycG9zZXMKYnBlX2RhdGEkZXJxX3N1cHBfaGwgPC0gaWZlbHNlKGJwZV9kYXRhJGVycV9zdXBwX2MgPj0gMCwgIkhpZ2giLCAiTG93IikKCmdncGxvdChkYXRhID0gYnBlX2RhdGEsIGFlcyh4ID0gc2xwaHJzLCB5ID0gcHJlZF9zdXBwWywiRXN0aW1hdGUiXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gZXJxX3N1cHBfaGwpKSArCiAgZ2VvbV9qaXR0ZXIoc2l6ZSA9IC43NSwgd2lkdGggPSAwLjM1KSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gbG0pICsKICB4bGFiKCJIb3VycyBvZiBTbGVlcCIpICsKICB5bGFiKCJOZWdhdGl2ZSBBZmZlY3QiKSArCiAgdGhlbWVfY2xhc3NpYygpICArCiAgdGhlbWUoYXhpcy50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT0xMiksCiAgICAgICAgYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgICAgICBwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE0LCBoanVzdD0uNSkpICsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJUaW1lcyBOZXcgUm9tYW4iKSkgKwogIGdndGl0bGUoIk5lZ2F0aXZlIEFmZmVjdCB2cy4gU2xlZXBcbmZvciBIaWdoIGFuZCBMb3cgU3VwcHJlc3Npb24gSW5kaXZpZHVhbHMiKSArCiAgbGFicyhjb2xvdXIgPSAiRXhwcmVzc2l2ZSBTdXBwcmVzc2lvbiBTY29yZSIpCmBgYAoKIyMjIFJlYWQgcGxvdAoKSW4gdGhpcyB2aXN1YWxpemF0aW9uLCBlYWNoIHBvaW50IHBsb3RzIGFuIGluZGl2aWR1YWwncyByZXBvcnRlZCAqKm5lZ2F0aXZlIGFmZmVjdCoqIG9uIGEgcGFydGljdWxhciBkYXkgYWdhaW5zdCB0aGUgbnVtYmVyIG9mICoqaG91cnMgb2Ygc2xlZXAqKiB0aGV5IHJlcG9ydCBmcm9tIHRoZSBwcmlvciBuaWdodC4gUG9pbnRzIGFyZSBjb2xvciBjb2RlZCB0byBpbmRpY2F0ZSB3aGV0aGVyIHRoZSBpbmRpdmlkdWFsIGhhcyBhIGhpZ2ggKGNvcmFsKSBvciBsb3cgKHR1cnF1b2lzZSkgKipleHByZXNzaXZlIHN1cHByZXNzaW9uKiogc2NvcmUuCgpUaGUgY29yYWwgcmVncmVzc2lvbiBsaW5lIHJlcHJlc2VudHMgdGhlIGFnZ3JlZ2F0ZSBvZiBpbmRpdmlkdWFscyB3aXRoIGhpZ2ggKipleHByZXNzaXZlIHN1cHByZXNzaW9uKiogc2NvcmVzLCB3aGlsZSB0aGUgdHVycXVvaXNlIHJlZ3Jlc3Npb24gbGluZSByZXByZXNlbnRzIHRoZSBhZ2dyZWdhdGUgb2YgaW5kaXZpZHVhbHMgd2l0aCBsb3cgKipleHByZXNzaXZlIHN1cHByZXNzaW9uKiogc2NvcmVzLiBUaGUgc2xvcGUgb2YgZWFjaCBsaW5lIGluZGljYXRlcyB0aGUgc3RyZW5ndGggb2YgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gKipob3VycyBvZiBzbGVlcCoqIGF0IG5pZ2h0IGFuZCAqKm5lZ2F0aXZlIGFmZmVjdCoqIHRoZSBmb2xsb3dpbmcgZGF5IGZvciB0aGF0IGdyb3VwLiBXZSBub3RlIHRoYXQgdGhlIGNvcmFsIGxpbmUgaGFzIGEgbW9yZSBuZWdhdGl2ZSBzbG9wZSB0aGFuIHRoZSB0dXJxdW9pc2UgbGluZSwgaW5kaWNhdGluZyBhIHN0cm9uZ2VyIGFzc29jaWF0aW9uIGJldHdlZW4gKipzbGVlcCoqIGFuZCAqKm5lZ2F0aXZlIGFmZmVjdCoqIGZvciB0aGUgaGlnaCAqKmV4cHJlc3NpdmUgc3VwcHJlc3Npb24qKiBncm91cC4KCiMjIyBJbnRlcnByZXQgcGxvdAoKV2Ugb2JzZXJ2ZSB0aGF0IGhhdmluZyBhIGhpZ2hlciAqKmV4cHJlc3NpdmUgc3VwcHJlc3Npb24qKiBzY29yZSBtYXkgcHJlZGljdCBhIGxhcmdlciBkaWZmZXJlbmNlIGluICoqbmVnYXRpdmUgYWZmZWN0KiogZm9yIGEgZml4ZWQgZGlmZmVyZW5jZSBpbiAqKmhvdXJzIG9mIHNsZWVwKiouIEluIG90aGVyIHdvcmRzLCBpdCBhcHBlYXJzIHRoYXQgdGhvc2Ugd2l0aCBoaWdoZXIgKipleHByZXNzaXZlIHN1cHByZXNzaW9uKiogc2NvcmVzIHJlcG9ydCAqKm5lZ2F0aXZlIGFmZmVjdCoqIHRoYXQgaXMgbW9yZSBjbG9zZWx5IHJlbGF0ZWQgdG8gaG93IG1hbnkgKipob3VycyBvZiBzbGVlcCoqIHRoZXkgZ290IHRoZSBwcmV2aW91cyBuaWdodC4gVGhpcyBtYXkgc3VnZ2VzdCB0aGF0ICoqZXhwcmVzc2l2ZSBzdXBwcmVzc2lvbioqIGlzIG1vc3QgZWZmZWN0aXZlIGluIGRlY3JlYXNpbmcgKipuZWdhdGl2ZSBhZmZlY3QqKiB3aGVuIGFuIGluZGl2aWR1YWwgaGFzIGdvdHRlbiBzdWZmaWNpZW50ICoqaG91cnMgb2Ygc2xlZXAqKi4KCldlIG9ic2VydmUgdGhhdCB0aGUgbW9kZXJhdGluZyBlZmZlY3RzIG9mICoqY29nbml0aXZlIHJlYXBwcmFpc2FsKiogYW5kICoqZXhwcmVzc2l2ZSBzdXBwcmVzc2lvbioqIGFwcGVhciBzaW1pbGFyLCBzdWdnZXN0aW5nIHRoYXQgYSBtb3JlIGdlbmVyYWwgZmFjdG9yIGlzIG1vZGVyYXRpbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuICoqaG91cnMgb2Ygc2xlZXAqKiBhbmQgKipuZWdhdGl2ZSBhZmZlY3QqKi4gV2UgbWF5IHdhbnQgdG8gaW52ZXN0aWdhdGUgdGhpcyBmdXJ0aGVyIGluIGZ1dHVyZSB3b3JrLgoKIyBNb2RlbCBjb21wYXJpc29uCgpXZSB3aWxsIG5vdyB1c2UgbGVhdmUtb25lLW91dCBjcm9zcy12YWxpZGF0aW9uIChMT09DVikgdG8gY29tcGFyZSB0aGUgcmVsYXRpdmUgZml0cyBvZiB0aGUgKipjb2duaXRpdmUgcmVhcHByYWlzYWwqKiBtb2RlbCBhbmQgdGhlICoqZXhwcmVzc2l2ZSBzdXBwcmVzc2lvbioqIG1vZGVsLiBUaGlzIHR5cGUgb2YgbW9kZWwgY29tcGFyaXNvbiBpcyB0eXBpY2FsbHkgZG9uZSBiZXR3ZWVuIHR3byBkaWZmZXJlbnQga2luZHMgb2YgbW9kZWxzIHVzaW5nIHRoZSBzYW1lIGRhdGEuIE91ciBtb2RlbHMgaGF2ZSB0aGUgc2FtZSBmb3JtIGJ1dCB1c2Ugc2xpZ2h0bHkgZGlmZmVyZW50IGRhdGEgKHJlYXBwcmFpc2FsIHByZWRpY3RvciB2cy4gc3VwcHJlc3Npb24gcHJlZGljdG9yKS4gSG93ZXZlciwgZm9yIGRlbW9uc3RyYXRpdmUgcHVycG9zZXMsIHdlIHdpbGwgc3RpbCBjb21wYXJlIHRoZW0gdXNpbmcgTE9PQ1YuCgpgYGB7ciBsb29jdn0KYnBlLnJlYXAgPC0gYWRkX2NyaXRlcmlvbihicGUucmVhcCwgYygibG9vIikpCmJwZS5zdXBwIDwtIGFkZF9jcml0ZXJpb24oYnBlLnN1cHAsIGMoImxvbyIpKQpsb29fY29tcGFyZShicGUucmVhcCwgYnBlLnN1cHApCmBgYAoKV2Ugb2JzZXJ2ZSB0aGF0IHRoZSAqKmNvZ25pdGl2ZSByZWFwcHJhaXNhbCoqIG1vZGVsIGFwcGVhcnMgdG8gaGF2ZSBhIGJldHRlciBmaXQgdGhhbiB0aGUgKipleHByZXNzaXZlIHN1cHByZXNzaW9uKiogbW9kZWwuIFRoaXMgaW5kaWNhdGVzIHRoYXQgdGhlIHJlbGF0aW9uc2hpcHMgYW1vbmcgdmFyaWFibGVzIGluIHRoZSAqKmNvZ25pdGl2ZSByZWFwcHJhaXNhbCoqIG1vZGVsIGFyZSBiZXR0ZXIgc3VpdGVkIHRvIGEgbGluZWFyIG1vZGVsIHRoYW4gdGhvc2UgaW4gdGhlICoqZXhwcmVzc2l2ZSBzdXBwcmVzc2lvbioqIG1vZGVsLiBBIExPT0NWIGNvbXBhcmlzb24gd291bGQgbGlrZWx5IGdpdmUgdXMgbW9yZSBoZWxwZnVsIGluZm9ybWF0aW9uIGlmIHdlIHdlcmUgY29tcGFyaW5nLCBmb3IgZXhhbXBsZSwgYSBsaW5lYXIgdmVyc2lvbiBvZiB0aGUgKipjb2duaXRpdmUgcmVhcHByYWlzYWwqKiBtb2RlbCBhbmQgYSBub25saW5lYXIgdmVyc2lvbiBvZiB0aGUgKipjb2duaXRpdmUgcmVhcHByYWlzYWwqKiBtb2RlbC4gIAoKQmV5b25kIHVzaW5nIGZvcm1hbCBxdWFudGl0YXRpdmUgdGVjaG5pcXVlcyBsaWtlIExPT0NWIGZvciBtb2RlbCBjb21wYXJpc29uLCBpdCBjYW4gYmUgaGVscGZ1bCB0byBjb21wYXJlIHRoZSBwbG90dGVkIHBvc3RlcmlvciBkaXN0cmlidXRpb25zIG9mIHBhcmFtZXRlcnMgYWNyb3NzIHRoZSB0d28gbW9kZWxzLiBUaGlzIGNhbiBoZWxwIHVzIHVuZGVyc3RhbmQgdGhlIHJlbGF0aXZlIGxldmVscyBvZiB1bmNlcnRhaW50eSB3ZSBoYXZlIGluIHRob3NlIG1vZGVscy4gIAoKIyBDb25jbHVzaW9uCgpTaGlmdGluZyBmcm9tIGEgZnJlcXVlbnRpc3QgdW5kZXJzdGFuZGluZyBvZiBwYXJhbWV0ZXIgZXN0aW1hdGlvbiB0byBhIEJheWVzaWFuIHVuZGVyc3RhbmRpbmcgY2FuIGJlIGNoYWxsZW5naW5nLCBhbmQgaXQgaXMgaW1wb3J0YW50IHRvIGNvbnNpZGVyIHRoZSBtZXJpdHMgYW5kIGRyYXdiYWNrcyBvZiBib3RoIGFwcHJvYWNoZXMuIEJheWVzaWFuIHBhcmFtZXRlciBlc3RpbWF0aW9uIGNhbiBzZWVtIHVuaW50dWl0aXZlIGF0IGZpcnN0LCBidXQgaXQgcHJvdmlkZXMgdXMgd2l0aCBuZXcgdG9vbHMgdG8gZGVzY3JpYmUgYW5kIGFuYWx5emUgdGhlIHVuY2VydGFpbnR5IGluaGVyZW50IGluIG91ciBkYXRhLiAqKkluIHNvY2lhbCBzY2llbmNlIHJlc2VhcmNoLCBiZWluZyBhYmxlIHRvIGluY29ycG9yYXRlIHN1YmplY3Rpdml0eSBpbnRvIG91ciBtb2RlbHMgY2FuIGdpdmUgdXMgYSBuZXcgb3V0bG9vayBvbiBwaGVub21lbmEgdGhhdCBhcmUgb2Z0ZW4gaGFyZCB0byBwaW4gZG93biBpbiBhIHN0YW5kYXJkIHF1YW50aXRhdGl2ZSBmcmFtZXdvcmsuKioKCiMjIEFkZGl0aW9uYWwgcmVzb3VyY2VzCgpJZiB5b3Ugd291bGQgbGlrZSB0byBsZWFybiBtb3JlIGFib3V0IHRoZSBjb25jZXB0cyBtZW50aW9uZWQgaW4gdGhpcyB0dXRvcmlhbCwgaGVyZSBhcmUgYSBmZXcgZXh0ZXJuYWwgcmVzb3VyY2VzOgoKKiBUaGUgbWF0aGVtYXRpY3MgYmVoaW5kIEJheWVzaWFuIHBhcmFtZXRlciBlc3RpbWF0aW9uOiBodHRwczovL2Njcm1hLnN0YW5mb3JkLmVkdS9+am9zL2JheWVzL0JheWVzaWFuX1BhcmFtZXRlcl9Fc3RpbWF0aW9uLmh0bWwKKiBBZHZhbmNlZCB0b3BpY3Mgb24gQmF5ZXNpYW4gcGFyYW1ldGVyIGVzdGltYXRpb246IGh0dHA6Ly93d3cuZWNlLnZpcmdpbmlhLmVkdS9+ZmZoOHgvZG9jcy90ZWFjaGluZy9lc2wvMjAyMC0wNC9mYXJub3VkLXNsZ20tY2hhcDAzLnBkZgoqIFRoZSBicm1zIHBhY2thZ2U6IGh0dHBzOi8vcGF1bC1idWVya25lci5naXRodWIuaW8vYnJtcy8KKiBDb25maWRlbmNlIGFuZCBjcmVkaWJsZSBpbnRlcnZhbHM6IGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcG1jL2FydGljbGVzL1BNQzY2MzAxMTMvCgojIFJlZmVyZW5jZXMKCkLDvHJrbmVyLCBQLi1DLiAoMjAxNykuIGJybXM6IEFuIFIgcGFja2FnZSBmb3IgQmF5ZXNpYW4gbXVsdGlsZXZlbCBtb2RlbHMgdXNpbmcgU3Rhbi4gKkpvdXJuYWwgb2YgU3RhdGlzdGljYWwgU29mdHdhcmUqLCAqODAqKDEpLiBodHRwczovL2RvaS5vcmcvMTAuMTg2MzcvanNzLnYwODAuaTAxCgpHcm9zcywgSi4gSi4sICYgSm9obiwgTy4gUC4gKDIwMDMpLiBJbmRpdmlkdWFsIGRpZmZlcmVuY2VzIGluIHR3byBlbW90aW9uIHJlZ3VsYXRpb24gcHJvY2Vzc2VzOiBJbXBsaWNhdGlvbnMgZm9yIGFmZmVjdCwgcmVsYXRpb25zaGlwcywgYW5kIHdlbGwtYmVpbmcuICpKb3VybmFsIG9mIFBlcnNvbmFsaXR5IGFuZCBTb2NpYWwgUHN5Y2hvbG9neSosICo4NSooMiksIDM0OOKAkzM2Mi4gaHR0cHM6Ly9kb2kub3JnLzEwLjEwMzcvMDAyMi0zNTE0Ljg1LjIuMzQ4CgpKb3ljZSwgSi4gKDIwMjEpLiBCYXllc+KAmSB0aGVvcmVtIChFLiBOLiBaYWx0YSwgRWQuKS4gKlRoZSBTdGFuZm9yZCBFbmN5Y2xvcGVkaWEgb2YgUGhpbG9zb3BoeSogKEZhbGwgMjAyMSBFZGl0aW9uKS4gaHR0cHM6Ly9wbGF0by5zdGFuZm9yZC5lZHUvYXJjaGl2ZXMvZmFsbDIwMjEvZW50cmllcy9iYXllcy10aGVvcmVtLyAoT3JpZ2luYWwgd29yayBwdWJsaXNoZWQgMjAwMykKCkthaG4sIE0uLCBTaGVwcGVzLCBHLiwgJiBTYWRlaCwgQS4gKDIwMTMpLiBTbGVlcCBhbmQgZW1vdGlvbnM6IEJpZGlyZWN0aW9uYWwgbGlua3MgYW5kIHVuZGVybHlpbmcgbWVjaGFuaXNtcy4gKkludGVybmF0aW9uYWwgSm91cm5hbCBvZiBQc3ljaG9waHlzaW9sb2d5KiwgKjg5KigyKSwgMjE44oCTMjI4LiBodHRwczovL2RvaS5vcmcvMTAuMTAxNi9qLmlqcHN5Y2hvLjIwMTMuMDUuMDEwCgpSYW0sIE4uLCBDb25yb3ksIEQuIEUuLCBQaW5jdXMsIEEuIEwuLCBIeWRlLCBBLiBMLiwgJiBNb2xsb3ksIEwuIEUuICgyMDEyKS4gVGV0aGVyaW5nIHRoZW9yeSB0byBtZXRob2Q6IFVzaW5nIG1lYXN1cmVzIG9mIGludHJhaW5kaXZpZHVhbCB2YXJpYWJpbGl0eSB0byBvcGVyYXRpb25hbGl6ZSBpbmRpdmlkdWFsc+KAmSBkeW5hbWljIGNoYXJhY3RlcmlzdGljcy4gSW4gRy4gSGFuY29jayAmIEouIEhhcnJpbmcgKEVkcy4pLCAqQWR2YW5jZXMgaW4gbG9uZ2l0dWRpbmFsIG1ldGhvZHMgaW4gdGhlIHNvY2lhbCBhbmQgYmVoYXZpb3JhbCBzY2llbmNlcyogKHBwLiA4MS0xMTApLiBOZXcgWW9yazogSW5mb3JtYXRpb24gQWdlLgoKKipZb3UgbWF5IG5vdyBzd2l0Y2ggYmFjayB0byB0aGUgUXVhbHRyaWNzIHN1cnZleSB0YWIuIFlvdSBjYW4gbGVhdmUgdGhpcyB0YWIgb3BlbiBhbmQgcmVmZXIgYmFjayB0byB0aGUgdHV0b3JpYWwgYXMgeW91IGNvbXBsZXRlIHRoZSByZXN0IG9mIHRoZSBzdXJ2ZXkuKioKCjwvZm9udD4=